﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using TheMovieDB;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.Reflection;
using TMS;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
using System.Xml;
using TMS.Classes;
using TMS.Forms;
using DevExpress.XtraEditors.Repository;

namespace TMDB
{
    public partial class TMSMain : Form
    {
        //BindingList<TmdbMovie> movies = new BindingList<TmdbMovie>();
        BindingList<TMSMovie> movies = new BindingList<TMSMovie>();
        BindingList<TMSFolderInfo> folders = new BindingList<TMSFolderInfo>();
        BindingList<Poster> posters = new BindingList<Poster>();
        Thread imageLoader;
        TMSMovie currentMovie;

        string directoriesfile = "";

        private int TotalProgress 
        {
            get;
            set;
        }
        private int TotalFiles
        {
            get;
            set;
        }
        private int FileProgress
        {
            get;
            set;
        }
        private void refreshTotalProgress()
        {
            int ntotalprogress = 0;
            int ntotalFiles = 0;
            int nfileprogress = 0;

            foreach (var item in folders)
            {
                ntotalprogress += item.Progress;
                ntotalFiles += item.TotalFiles;
                nfileprogress += item.FileProgress;
            }
            if (folders.Count == 0)
                TotalProgress = 0;
            else
                TotalProgress = Convert.ToInt32(((decimal)ntotalprogress / (decimal)folders.Count));


            TotalFiles = ntotalFiles;
            FileProgress = nfileprogress;

            fileprogress.EditValue = TotalProgress;
            lblStatus.Text = "Processing File " + nfileprogress.ToString() + "/" + ntotalFiles.ToString();      
        }

        int total = 0;
        int current = 0;

        public TMSMain()
        {
            InitializeComponent();
            gridControl1.DataSource = movies;
            try
            {
                txtProxyServer.Text = System.Net.WebProxy.GetDefaultProxy().Address.AbsoluteUri;
            }
            catch (Exception)
            {
                
            }
            directoriesfile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\directories.txt";
            grdPosters.DataSource = posters;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fdr = new FolderBrowserDialog();
            if (fdr.ShowDialog() == DialogResult.OK)
                txtFolder.Text = fdr.SelectedPath;

        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
            movies.Clear();
        }

        //private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        //{
        //    if (tabControl1.SelectedIndex == 1)
        //    {
        //        int row = gridView1.FocusedRowHandle;
        //        if (row != -1)
        //        {
        //            ImageList imgList = new ImageList();
        //            imgList.ImageSize = new System.Drawing.Size(256, 256);
        //            imgList.ColorDepth = ColorDepth.Depth16Bit;
        //            listView1.LargeImageList = imgList;
        //            listView1.Items.Clear();
        //            List<TmdbImage> moviesImages = movies[row].Images;
        //            List<TmdbImage> shortList = new List<TmdbImage>();
        //            List<String> imagety = new List<string>();

        //            for (int i = 0; i < 10; i++)
        //            {
        //                if (moviesImages[i].Type == TmdbImageType.poster)
        //                {
        //                    shortList.Add(moviesImages[i]);    
        //                }
        //            }

        //            foreach (var image in shortList)
        //            {
        //                WebClient webClient = new WebClient();
        //                //WebProxy proxy = new WebProxy("Http://sapphire:8080");
        //                //proxy.Credentials = new NetworkCredential("Demo", "show", "shirebrn");
        //                //webClient.Proxy = proxy;
        //                byte[] webClientDownloadData = webClient.DownloadData(new Uri(image.Url));
        //                if (webClientDownloadData != null)
        //                {
        //                    try
        //                    {
        //                        Bitmap img = new Bitmap(new MemoryStream(webClientDownloadData));
        //                        Invoke(new MethodInvoker(() =>
        //                        {
        //                            imgList.Images.Add(image.Id, img);
        //                            listView1.Items.Add(Path.GetFileName(image.Url), image.Id);
        //                            this.Refresh();
        //                        }));

        //                    }
        //                    catch (Exception Ex)
        //                    {
        //                    }
        //                }
        //                else { }
        //            }

        //            //Parallel.ForEach(shortList, image =>
        //            //{
        //            //    WebClient webClient = new WebClient();
        //            //    WebProxy proxy = new WebProxy("Http://sapphire:8080");
        //            //    proxy.Credentials = new NetworkCredential("Demo", "show", "shirebrn");
        //            //    webClient.Proxy = proxy;
        //            //    byte[] webClientDownloadData = webClient.DownloadData(new Uri(image.Url));
        //            //    if (webClientDownloadData != null)
        //            //    {
        //            //        try
        //            //        {
        //            //            Bitmap img = new Bitmap(new MemoryStream(webClientDownloadData));
        //            //            Invoke(new MethodInvoker(() =>
        //            //            {
        //            //                imgList.Images.Add(image.Id, img);
        //            //                listView1.Items.Add(Path.GetFileName(image.Url), image.Id);
        //            //            }));

        //            //        }
        //            //        catch (Exception Ex)
        //            //        {
        //            //        }
        //            //    }
        //            //    else { }
        //            //});
        //        }
        //    }
        //}

        private void timer1_Tick(object sender, EventArgs e)
        {
            gridView1.RefreshData();
            FoldersGridView.RefreshData();
            refreshTotalProgress();
        }

        
        private void btnGetFolder_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fdr = new FolderBrowserDialog();
            if (fdr.ShowDialog() == DialogResult.OK)
                txtFolder.Text = fdr.SelectedPath;
        }

        private void btnProcess_Click(object sender, EventArgs e)
        {
            processFolders();
            //xtraTabControl1.SelectedTabPage = xtraTabPage2;
            //processFiles();
        }

        private void processFolders()
        {
            foreach (var item in folders)
            {
                processfolder(item);
            }
        }
        private void processfolder(TMSFolderInfo fi) 
        {
            fi.ProxyAddress = txtProxyServer.Text;
            fi.FileExtensions = txtFileExtensions.Text;
            fi.OnMovieAdded += new EventHandler(Form1_OnMovieAdded);
            fi.OnMovieInfoReady += new EventHandler<OnMovieInfoReadyEventArgs>(item_OnMovieInfoReady);
            fi.OnMovieInfoRefresh += new EventHandler(fi_OnMovieInfoRefresh);
            try
            {
                fi.LoadDirectoryInfo();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Loading Directory", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        
        }

        void fi_OnMovieInfoRefresh(object sender, EventArgs e)
        {
            item_OnMovieInfoReady(sender, null);
        }

        void item_OnMovieInfoReady(object sender, OnMovieInfoReadyEventArgs e)
        {
            if (InvokeRequired)
            {
                if (this != null)
                {
                    Invoke(new MethodInvoker(() =>
                    {
                        if (this != null)
                            item_OnMovieInfoReady(sender, e);
                    }));
                }
            }
            else
            {
                TMSMovie clonedObj = (TMSMovie)((TMSMovie)sender).Clone();
                bool lfound = false;
                TMSMovie current;
                int index = 0;
                foreach (var item in movies)
                {

                    if (item.UniqueID == clonedObj.UniqueID)
                    {
                        lfound = true;
                        break;
                    }
                    index++;
                }
                if (lfound)
                    movies[index] = clonedObj;

                return;
            }            
        }

        void Form1_OnMovieAdded(object sender, EventArgs e)
        {
            if (InvokeRequired)
            {
                if (this != null)
                {
                    Invoke(new MethodInvoker(() =>
                    {
                        if (this != null)
                            Form1_OnMovieAdded(sender, e);
                    }));
                }
            }
            else
            {
                TMSMovie clonedObj = (TMSMovie)((TMSMovie)sender).Clone();
                movies.Add(clonedObj);
            }
        }

        private void btnAddFolder_Click(object sender, EventArgs e)
        {
            foreach (string item in txtFolder.Text.Split(";".ToCharArray()))
            {
                TMSFolderInfo tmdbfi = new TMSFolderInfo() { DirectoryPath = item };
                if (String.IsNullOrEmpty(txtName.Text.Trim()))
                    tmdbfi.Name = item;
                else
                    tmdbfi.Name  = txtName.Text.Trim();

                folders.Add(tmdbfi);
                lstFolders.Refresh();
                processfolder(tmdbfi);
            }
            
            saveToFile();
            txtFolder.Text = "";
        }

        private void saveToFile() 
        {
            StringBuilder sb = new StringBuilder();
            foreach (TMSFolderInfo item in folders)
            {
                sb.AppendLine(item.Name + ";" + item.DirectoryPath);
            }
            File.WriteAllText(directoriesfile, sb.ToString());
        }

        private void xtraTabPage1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            lstFolders.DataSource = folders;
            loadfromFile();
            gridView1.OptionsView.AnimationType = DevExpress.XtraGrid.Views.Base.GridAnimationType.AnimateAllContent;
            //if (File.Exists(directoriesfile))
            //{
            //    var directories = File.ReadAllLines(directoriesfile);
            //    foreach (string item in directories)
            //    {
            //        var folderinfo = item.Split(";".ToCharArray());
            //        if (folderinfo.Length == 2)
            //        {
            //            TMSFolderInfo tmdbfi = new TMSFolderInfo() { Name = folderinfo[0], DirectoryPath = folderinfo[1] };
            //            folders.Add(tmdbfi);
            //            FoldersGridView.RefreshData();
            //        }
            //    }
            //    processFolders();

            //    FoldersGridView.FocusedRowHandle = 1;
            //    lstFolders.Focus();
            //    //lstFolders.SelectedIndex = 1;
            //}
        }

        private void btnRemoveFolder_Click(object sender, EventArgs e)
        {
            TMSFolderInfo tmdbfi = (TMSFolderInfo)FoldersGridView.GetFocusedRow();
            if (tmdbfi != null)
            {
                folders.Remove(tmdbfi);
                FoldersGridView.RefreshData();
            }
            //if (lstFolders.SelectedIndex >= 0)
            //{
            //    lstFolders.Items.RemoveAt(lstFolders.SelectedIndex);
            //}
            saveToFile();
        }

        private void loadimages(object imagelist) 
        {
            var list = (List<TmdbImage>)imagelist;

            using (WebClient wc = new WebClient())
            {
                if (!string.IsNullOrEmpty(txtProxyServer.Text))
                {
                    WebProxy proxy = new WebProxy(txtProxyServer.Text);
                    proxy.BypassProxyOnLocal = true;
                    proxy.UseDefaultCredentials = true;
                    wc.Proxy = proxy;
                }

                int currentImage = 0;
                foreach (var item in list)
                {
                    currentImage++;
                    try
                    {
                        byte[] data = wc.DownloadData(new Uri(item.Url));

                        System.Drawing.Image newImage;

                        using (MemoryStream ms = new MemoryStream(data, 0, data.Length))
                        {
                            ms.Write(data, 0, data.Length);
                            newImage = System.Drawing.Image.FromStream(ms, true);
                            if (InvokeRequired)
                            {
                                Invoke(new MethodInvoker(() =>
                                {
                                    if (currentImage == 1)
                                    {
                                        imgThumb.Image = newImage;
                                        pnlLoadingImage.Visible = false;
                                    }
                                    else
                                    {
                                        posters.Add(new Poster(newImage));
                                        postersView.RefreshData();
                                    }
                                }));
                            }
                            else
                            {
                                if (currentImage == 1)
                                {
                                    imgThumb.Image = newImage;
                                    pnlLoadingImage.Visible = false;
                                }
                                else
                                {
                                    posters.Add(new Poster(newImage));
                                }
                            }
                        }
                    }
                    catch (Exception)
                    {
                        
                    }
                }
                
            }
        }

        void mainImage_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
        {
            System.Drawing.Image newImage;
            
            using (MemoryStream ms = new MemoryStream(e.Result, 0, e.Result.Length))
            {

                ms.Write(e.Result, 0, e.Result.Length);

                newImage = System.Drawing.Image.FromStream(ms, true);
                imgThumb.Image = newImage;
                pnlLoadingImage.Visible = false;
                // work with image here. 

                // You'll need to keep the MemoryStream open for 
                // as long as you want to work with your new image. 

            }
            //e.Result
        }
        
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (imageLoader != null)
                imageLoader.Abort();
        }

        private void gridControl1_DoubleClick(object sender, EventArgs e)
        {
            pgFileInfo.PageEnabled = true; 
            currentMovie = (TMSMovie)gridView1.GetFocusedRow();
            xtraTabControl1.SelectedTabPage = pgFileInfo;
        }

        private void pgFileInfo_Enter(object sender, EventArgs e)
        {
            TMSMovie movie = currentMovie;

            lblTitle.Text = movie.FilmName + " (" + movie.Released.Value.Year.ToString() + ")";

            WebClient webClient = new WebClient();

            imgThumb.Image = null;
            lblOverview.Text = movie.Overview;
            posters.Clear();

            if (movie.Images != null && movie.Images.Count > 0)
            {
                pnlLoadingImage.Visible = true;

                if (imageLoader == null)
                {
                    imageLoader = new Thread(new ParameterizedThreadStart(loadimages));
                    imageLoader.Start(movie.Images);
                }
                else
                {
                    imageLoader.Abort();
                    imageLoader = new Thread(new ParameterizedThreadStart(loadimages));
                    imageLoader.Start(movie.Images);
                }
            }
        }

        private void gridView1_RowCellStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowCellStyleEventArgs e)
        {
            var movie = (TMSMovie)gridView1.GetRow(e.RowHandle);
            if (movie.MovieInfoState == TMDBMovieInfoState.InfoNotFound)
                e.Appearance.BackColor = Color.Salmon;
        }

        private void loadfromFile()
        {
            string filename = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\movies.xml";
            if (File.Exists(filename))
            {

                XmlSerializer serializer = new
                XmlSerializer(typeof(List<TMSFolderInfo>));

                // A FileStream is needed to read the XML document.
                FileStream fs = new FileStream(filename, FileMode.Open);
                XmlReader reader = new XmlTextReader(fs);

                var i = (List<TMSFolderInfo>)serializer.Deserialize(reader);
                i.ForEach(folder => 
                { 
                    folders.Add(folder);
                    folder.Movies.ForEach(movie =>
                    {
                        
                        //bool lfound = false;
                        //TMSMovie current;
                        //int index = 0;
                        //foreach (var item in movies)
                        //{
                        //    if (item.UniqueID == movie.UniqueID)
                        //    {
                        //        lfound = true;
                        //        break;
                        //    }
                        //    index++;
                        //}
                        //if (lfound)
                        //    movies[index] = movie;
                        //else
                        movies.Add(movie);
                    });
                    processfolder(folder);
                });
                



            }

        
        } 
        private void savelist(List<TMSMovie> movielist)
        {
            string filename = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\movies.xml";
            XmlSerializer serializer = new XmlSerializer(typeof(List<TMSFolderInfo>));
            TextWriter writer = new StreamWriter(filename);

            List<TMSFolderInfo> tmpFolders = new List<TMSFolderInfo>();
            foreach (var item in folders)
            {
                tmpFolders.Add(item);
            }

            serializer.Serialize(writer, tmpFolders);
            writer.Close();
        }

        private void btnSerialize_Click(object sender, EventArgs e)
        {
            List<TMSMovie> tmpMovies = new List<TMSMovie>();
            foreach (var item in folders)
	        {
                item.Movies.ForEach(movie => tmpMovies.Add((TMSMovie)movie.Clone()));
	        }
            savelist(tmpMovies);
            
        }

        private void btnAddToDb_Click(object sender, EventArgs e)
        {
            Entity ent = new Entity();
            
        }

        private void mnuitmChangeFriendlyName_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            string friendlyName = "";

            List<TMSMovie> selectedmovies = new List<TMSMovie>();

            foreach (int index in gridView1.GetSelectedRows())
            {
                selectedmovies.Add((TMSMovie)gridView1.GetRow(index));
            }

            if (selectedmovies.Count == 1)
                if (String.IsNullOrEmpty(selectedmovies[0].FriendlyName))
                    friendlyName = selectedmovies[0].FilmName;
                else
                    friendlyName = selectedmovies[0].FriendlyName;
            
            FrmChangeFriendlyName cfn = new FrmChangeFriendlyName(friendlyName);
            cfn.ShowDialog();

            if (cfn.DialogResult == System.Windows.Forms.DialogResult.OK)
            {

                ThreadPool.QueueUserWorkItem(new WaitCallback(obj =>
                {

                    Parallel.ForEach(selectedmovies, movie =>
                    {
                        foreach (var item in folders)
                        {
                            if (item.DirectoryPath == Path.GetDirectoryName(movie.Filename).Substring(0,item.DirectoryPath.Length))
                            {
                                TMSMovie tmsmovie = item.Movies.Find(mov => mov.UniqueID == movie.UniqueID);
                                if (tmsmovie != null)
                                {
                                    tmsmovie.FriendlyName = cfn.FriendlyName;
                                    tmsmovie.ForceRefreshInfo();
                                    tmsmovie.LoadMovieInfo();
                                }

                            }
                        }
                        //
                        //TMSMovie myMovie = (TMSMovie)movie.Clone();
                        //movie.FriendlyName = cfn.FriendlyName;
                        //movie.LoadMovieInfo();
                    });
                }));
            
                //}));
            }

        }

      

        private void gridControl1_MouseClick(object sender, MouseEventArgs e)
        {
           
        }

        private void TMSMain_MouseClick(object sender, MouseEventArgs e)
        {
            //if (e.Button == System.Windows.Forms.MouseButtons.Right)
            //    mnuOptions.ShowPopup(new Point(e.X , e.Y ));
        }

        private void gridControl1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
                mnuOptions.ShowPopup(new Point(e.X + this.Left + 16, e.Y + this.Top+60));
        }

        private void gridView1_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e)
        {
            
        }

        private void mnuRefreshInfo_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {

            ThreadPool.QueueUserWorkItem(new WaitCallback(obj =>
            {
                List<TMSMovie> selectedmovies = new List<TMSMovie>();

                foreach (int index in gridView1.GetSelectedRows())
                {
                    selectedmovies.Add((TMSMovie)gridView1.GetRow(index));
                }

                Parallel.ForEach(selectedmovies, movie =>
                {
                    foreach (var item in folders)
                    {
                        if (item.DirectoryPath == Path.GetDirectoryName(movie.Filename))
                        {
                            TMSMovie tmsmovie = item.Movies.Find(mov => mov.UniqueID == movie.UniqueID);
                            if (tmsmovie != null)
                            {
                                tmsmovie.ForceRefreshInfo();
                                tmsmovie.LoadMovieInfo();
                            }
                        }
                    }
                });
            }));
        }

       

       
    }
}